qt-bugs@ issue : N240326
Qt Software task ID : 240608
bugs.kde.org number : none
applied: no
author: George Goldberg <grundleborg@googlemail.com>

This patch fixes deserialization of values with custom types when setting
properties on dbus adaptors. It is needed, in particular by telepathy/Qt
programs and libraries. The bug was reported to Nokia on 2009-01-07 along
with the patch supplied here. The summary of the issue from the Qt
Software task tracker follows:

When calling the setter for a DBus property, if that property has a custom type
(e.g. a struct with dbus type (uss)), QtDBus fails to demarshall the
QDBusArgument before attempting to set the property on the adaptor. The result
is that it attempts to call adaptor->setProperty() with a QDBusArgument of type
"uss" instead of with the type of the custom struct.

Index: src/dbus/qdbusinternalfilters.cpp
===================================================================
--- src/dbus/qdbusinternalfilters.cpp	(revision 960506)
+++ src/dbus/qdbusinternalfilters.cpp	(working copy)
@@ -274,9 +274,23 @@
             QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
             it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
                              interface_name);
-            if (it != connector->adaptors.end() && interface_name == QLatin1String(it->interface))
+            if (it != connector->adaptors.end() && interface_name == QLatin1String(it->interface)) {
+                if (value.userType() == qMetaTypeId<QDBusArgument>()) {
+                    QDBusArgument valueArg = qvariant_cast<QDBusArgument>(value);
+                    if (valueArg.currentType() != -1) {
+                        int mid = it->adaptor->metaObject()->property(it->adaptor->metaObject()->indexOfProperty(property_name)).userType();
+                        void *null = 0;
+                        QVariant valueStore(mid, null);
+                        QDBusMetaType::demarshall(valueArg, mid, valueStore.data());
+
+                        if (it->adaptor->setProperty(property_name, valueStore))
+                            return msg.createReply();
+                    }
+                }
+
                 if (it->adaptor->setProperty(property_name, value))
                     return msg.createReply();
+            }
         }
     }
 
